;;########################################################################
;; efa-visualize.lsp
;;########################################################################

(defmeth efa-model-object-proto :visualize ()
  (if (not (eq current-object self)) (setcm self))
  (let* ((factor-load (column-list (send self :factor-load)))
         
         (nvar (send self :nvars))
         (nfactors (send self :nfactors))
         (rays (row-list (select (transpose (send self :factor-load))
                        (iseq nfactors) (iseq nvar))))
         (nobs (send self :nobs))        
         (factor-labels (select '("Factor1" "Factor2" "Factor3" "Factor4" "Factor5") 
                             (iseq  nfactors)))
         (point-labels (send self :labels))
         (variable-labels (send self :variables))
         (evals (send current-model :init-eigenvalues))
         (proportions (/ evals (sum evals)))
         
         (scree (scree-plot proportions :show nil)) 
         
         (scatterplot (plot-points factor-load
                      :point-labels variable-labels :variable-labels factor-labels :title "Ray" :show nil))
         (spin-plot (if (> nfactors 2)
              (spin-plot factor-load :point-labels variable-labels :variable-labels factor-labels
                         :show nil)
              nil))
         

    (sp (spread-plot 
              (matrix '(1 3)
                          (list scree scatterplot spin-plot))))    
                       )
;;;;;;scatterplot 
(send scatterplot :add-rays factor-load :ray-labels nil :ray-color 'red)
(send scatterplot :adjust-scatterplot-to-data 'centroid-fixed)
    (send scatterplot :point-color (iseq nvar) 'red)   
    (send scatterplot :plot-buttons)   
    (send scatterplot :add-grid)
    (send scatterplot :linked t)
    (send scatterplot :showing-labels t)
    (send scatterplot :menu-template 
      '(SHOWING-LABELS MOUSE RESIZE-BRUSH DASH SYMBOL COLOR line-width))
    (send scatterplot :new-menu)
 
 (defmeth scatterplot-proto :show-new-var (axis variable)
      (let* ((cur-var (send self :current-variables))
             (var-num (position variable (send self :variable-labels))))
        (if (equal axis "X") 
            (send self :current-variables var-num (second cur-var) :draw nil)
            (send self :current-variables (first cur-var) var-num :draw nil))
        (apply #' send self :y-axis (send self :y-axis))
        (send self :add-grid)
        (send self :redraw)))

;;;;spin-plot
    (send spin-plot :scale-type 'fixed);xls bug work-around
          (send spin-plot :point-symbol 
                (iseq (send spin-plot :num-points)) 'disk)
          (send spin-plot :point-color (iseq nvar) 'white)
          (send spin-plot :mouse-mode 'hand-rotate)
          ;(send spin-plot :scale-constant 1.5 :draw nil)
          ;(send spin-plot :scale-type 'centroid-fixed)
          (send spin-plot :linked t)
          (send spin-plot :showing-labels t)
          (send spin-plot :menu-template 
                '(SHOWING-LABELS MOUSE RESIZE-BRUSH DASH 
                                 SYMBOL COLOR line-width DASH FASTER SLOWER AXES))
          ;(send spin-plot :new-menu)
          ;(send spin-plot :add-box)
          ;(send spin-plot :switch-add-box)
          (setf dimension-lengths 
                (mapcar #'max (abs (send spin-plot :range (iseq nfactors )))))
          (setf rays-mat (matrix (list nfactors nvar) (combine rays)))
          (setf vector-lengths (sqrt (mapcar #'ssq (column-list rays-mat))))
          (setf spin-vector-ratio (sqrt (/ (^ (min dimension-lengths) 2)
                                           (^ (max vector-lengths) 2))))
          (setf rays (* rays spin-vector-ratio))
          (send spin-plot :add-rays rays :ray-labels variable-labels 
                :ray-color 'red)

 (defmeth spin-plot :show-new-var (axis variable)
            (let* ((var-num (position variable (send self :variable-labels)))
                   (cur-vars (send self :current-variables))
                   (cur-var-names nil)
                   (idling (send self :idle-on))
                   )
              (cond
                ((equal (string-downcase axis) "x") 
                 (setf (select cur-vars 0) var-num))
                ((equal (string-downcase axis) "y") 
                 (setf (select cur-vars 1) var-num))
                ((equal (string-downcase axis) "z") 
                 (setf (select cur-vars 2) var-num))
                )
              (setf cur-var-names (select (send self :variable-labels) cur-vars))
              (send self :idle-on nil)
              (send self :transformation nil)
              (apply #'send self :current-variables cur-vars)
              (send self :set-variables-with-labels cur-vars cur-var-names)
              ; (send spin-plot :add-rays rays :ray-labels variable-labels)
              (send self :redraw)
              (send self :idle-on idling)))
 
;=-=-=-=-= scree 
   (setf eigenvalues2 
          (mapcar #'(lambda (k)
                      (exp  (+ 
                             -0.130827
                             (* -0.444853 k)
                             (* -0.008497 (* k k)) 
                             (* 0.639462 (log nvar))
                             (* (* 0.059901 k) (log Nobs))
                             (* -0.078631 (* (log Nobs) (log nvar)))
                             (* (* 0.001488 (* k k)) (log Nvar))
                             (* (* 0.095875 k) (log nvar))
                             (* (* 0.001576 (* k k)) (log nvar))
                             (* (* -0.013331 k) (* (log Nobs) (log nvar)))
                             (* (* -0.000278 (* k k)) (* (log Nobs) (log nvar)))
                             ))) (iseq nvar)))
         (setf prop2 (/ eigenvalues2 (sum eigenvalues2)))

    (send scree :add-lines 
              (list (+ 1 (iseq nvar)) prop2) :draw nil :color 'dark-green)
    (send scree :variable-label 1 "Proportion")
    (send scree :range 1 0 
          (/ (ceiling (* 10 (select proportions 0))) 10) )      
    (send scree :x-axis t 0 (+ nvar 1))
    (send scree :range 0 0 nvar)
    (send scree :plot-buttons :mouse-mode nil :new-x nil :new-y nil)
    
    (send sp :size 500 500)
    (send sp :show-spreadplot)
    t))